package com.dc.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dc.project.constant.ConstantCommon;
import com.dc.project.entity.bo.TaskBo;
import com.dc.project.entity.map.TaskMapVo;
import com.dc.project.entity.po.Task;
import com.dc.project.entity.po.TaskDetailItem;
import com.dc.project.entity.query.TaskQuery;
import com.dc.project.entity.vo.TaskDetailItemVo;
import com.dc.project.entity.vo.TaskDetailVo;
import com.dc.project.entity.vo.TaskFileCommitVo;
import com.dc.project.entity.vo.TaskResultGenerateVo;
import com.dc.project.entity.vo.TaskVo;
import com.dc.project.mapper.TaskMapper;
import com.dc.project.service.TaskDetailItemService;
import com.dc.project.service.TaskDetailService;
import com.dc.project.service.TaskFileCommitService;
import com.dc.project.service.TaskResultGenerateService;
import com.dc.project.service.TaskService;
import com.dc.project.util.TaskPasswordUtil;
import com.own.business.resource.business.service.FileRecordService;
import com.own.business.resource.entity.po.FileRecord;
import com.own.business.resource.entity.vo.FileRecordVo;
import com.own.component.common.base.service.impl.AbstractBaseService;
import com.own.component.common.util.encrypt.EncryptUtil;
import com.own.util.list.ListUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * TaskServiceImpl
 *
 * @author chenxueli
 * @date 2025-03-08 15:11:52
 */
@Slf4j
@Service
public class TaskServiceImpl extends AbstractBaseService<
        Task,
        TaskBo,
        TaskVo,
        TaskMapVo,
        TaskQuery,
        TaskMapper
        > implements TaskService {

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private TaskDetailService taskDetailService;
    @Resource
    private TaskDetailItemService taskDetailItemService;
    @Resource
    private FileRecordService fileRecordService;
    @Resource
    private TaskFileCommitService taskFileCommitService;
    @Resource
    private TaskResultGenerateService taskResultGenerateService;

    @Resource
    private TaskPasswordUtil taskPasswordUtil;

    /**
     * 获取查询条件
     *
     * @param query 查询条件
     * @return 查询条件对象
     */
    @Override
    public LambdaQueryWrapper<Task> lambdaQueryWrapper(TaskQuery query) {
        return super.lambdaQueryWrapper(query)
                .like(StringUtils.isNotBlank(query.getTitle()), Task::getTitle, query.getTitle())
                .eq(query.getStatus() != null, Task::getStatus, query.getStatus())
                .eq(query.getType() != null, Task::getType, query.getType())
                .eq(query.getIsHot() != null, Task::getIsHot, query.getIsHot())
                .eq(StringUtils.isNotBlank(query.getTemplateKey()), Task::getTemplateKey, query.getTemplateKey())
                .orderByDesc(Task::getIsHot)
                .orderByDesc(Task::getGmtCreate)
                .orderByDesc(Task::getId);
    }

    /**
     * 根据任务id修改任务名称
     *
     * @param id    任务id
     * @param title 任务名称
     */
    @Override
    public void updateTitle(Long id, String title) {
        var po = getPoById(id);
        po.setTitle(title);
        taskMapper.updateById(po);
    }

    /**
     * 根据文件列表创建任务
     *
     * @param companyName 企业名称
     * @param fileIdList  文件ID列表
     * @return 任务信息
     */
    @Override
    public TaskVo createByFileList(String companyName, List<Long> fileIdList) {
        // 生成任务名称
        var taskName = "任务-" + System.currentTimeMillis();
        var task = new Task();
        task.setTitle(taskName);
        task.setCompanyName(companyName);
        task.setStatus(1);
        task.setIsHot(0);
        task.setIsEncrypt(0);
        task.setType(ConstantCommon.Type.CREATE_BY_CUSTOM_FILE);
        // 保存任务
        taskMapper.insert(task);
        // 创建任务详情信息
        taskDetailService.createByFileList(task, fileIdList);
        return ofVo(task);
    }

    /**
     * 根据模板key创建
     *
     * @param companyName 企业名称
     * @param realmName   领域名称
     * @param templateKey 模板key
     * @return 任务信息
     */
    @Override
    public TaskVo createByTemplateKey(String companyName, String realmName, String templateKey) {
        // 生成任务名称
        var taskName = "任务-" + System.currentTimeMillis();
        var task = new Task();
        task.setTitle(taskName);
        task.setCompanyName(companyName);
        task.setRealmName(realmName);
        task.setStatus(1);
        task.setIsHot(0);
        task.setIsEncrypt(0);
        task.setType(ConstantCommon.Type.CREATE_BY_TEMPLATE);
        task.setTemplateKey(templateKey);
        // 保存任务
        taskMapper.insert(task);
        // 添加详情信息
        taskDetailService.createByTemplateKey(task, templateKey);
        return ofVo(task);
    }

    /**
     * 根据任务id切换热门
     *
     * @param taskId 任务id
     */
    @Override
    public void changeHot(Long taskId) {
        var po = getPoById(taskId);
        po.setIsHot((po.getIsHot() + 1) % 2);
        taskMapper.updateById(po);
    }

    /**
     * 根据任务id修改领域名称
     *
     * @param taskId    任务id
     * @param realmName 领域名称
     */
    @Override
    public void updateRealmName(Long taskId, String realmName) {
        var po = getPoById(taskId);
        po.setRealmName(realmName);
        taskMapper.updateById(po);
    }

    /**
     * 修改任务密码
     *
     * @param taskId      任务id
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     */
    @Override
    public void updatePassword(Long taskId, String oldPassword, String newPassword) {
        // 查询任务数据
        var po = getPoById(taskId);
        // 验证密码是否正确
        taskPasswordUtil.check(po.getPassword(), oldPassword);
        // 设置新密码
        var wrapper = new LambdaUpdateWrapper<Task>()
                .eq(Task::getId, taskId)
                .set(Task::getPassword, EncryptUtil.MD5.encrypt(newPassword))
                .set(Task::getIsEncrypt, 1);
        taskMapper.update(null, wrapper);
    }

    /**
     * 清除任务密码
     *
     * @param taskId   任务id
     * @param password 访问密码
     */
    @Override
    public void clearPassword(Long taskId, String password) {
        // 查询任务数据
        var po = getPoById(taskId);
        // 验证密码是否正确
        taskPasswordUtil.check(po.getPassword(), password);
        // 清除密码
        var wrapper = new LambdaUpdateWrapper<Task>()
                .eq(Task::getId, taskId)
                .set(Task::getPassword, "")
                .set(Task::getIsEncrypt, 0);
        taskMapper.update(null, wrapper);
    }

    /**
     * 根据任务id修改任务提示词
     *
     * @param taskId  任务id
     * @param content 任务提示词
     */
    @Override
    public void updatePromptByTaskId(Long taskId, String content) {
        var po = getPoById(taskId);
        po.setPrompt(content);
        taskMapper.updateById(po);
    }

    /**
     * 根据id获取信息之后处理的信息
     *
     * @param vo vo对象
     * @return 处理的vo对象
     */
    @Override
    public TaskVo afterGetById(TaskVo vo) {
        super.afterGetById(vo);
        if (vo == null) {
            return null;
        }
        var taskId = vo.getId();
        // 根据任务id查询任务的详情信息列表
        var detailList = taskDetailService.listByTaskId(taskId).stream().map(TaskDetailVo::new).toList();
        // 查询详情信息的分析数据
        var itemList = taskDetailItemService.listByTaskId(taskId);
        var itemMap = itemList.stream().collect(Collectors.groupingBy(TaskDetailItem::getFkDetailId, Collectors.mapping(TaskDetailItemVo::new, Collectors.toList())));
        // 查询所有提交的材料信息
        var commitList = taskFileCommitService.listByTaskId(taskId).stream().map(TaskFileCommitVo::new).toList();
        var treeCommitList = ListUtil.Tree
                .build(commitList, TaskFileCommitVo::getId, TaskFileCommitVo::getParentCommitId, TaskFileCommitVo::getChildren)
                .stream()
                // 只查询出没有上级的数据
                .filter(item -> item.getParentCommitId() == null)
                .toList();
        // 进行分组
        var commitTypeMap = treeCommitList.stream().collect(Collectors.groupingBy(TaskFileCommitVo::getType));
        // 获取所有的detail的信息
        var commitDetailMap = commitTypeMap.getOrDefault(2, List.of()).stream().collect(Collectors.groupingBy(TaskFileCommitVo::getTargetId));
        // 获取所有的item的信息
        var commitItemMap = commitTypeMap.getOrDefault(3, List.of()).stream().collect(Collectors.groupingBy(TaskFileCommitVo::getTargetId));
        // 查询所有的生成的文件信息
        var generateList = taskResultGenerateService.listByTaskId(taskId).stream().map(TaskResultGenerateVo::new).toList();
        var generateMap = generateList.stream().collect(Collectors.groupingBy(TaskResultGenerateVo::getItemId));
        // 获取所有的附件id
        var fileIdList = Stream
                .of(
                        detailList.stream().map(TaskDetailVo::getFileId),
                        commitList.stream().map(TaskFileCommitVo::getFileId),
                        generateList.stream().map(TaskResultGenerateVo::getFileId)
                )
                .flatMap(Function.identity())
                .distinct()
                .collect(Collectors.toList());
        var fileList = fileRecordService.listByIdList(fileIdList);
        var fileMap = fileList.stream().collect(Collectors.toMap(FileRecord::getId, FileRecordVo::new));
        // 设置commit中的文件信息
        commitList.forEach(commit -> commit.setFileRecord(fileMap.get(commit.getFileId())));
        // 设置生成的文件信息
        generateList.forEach(generate -> generate.setFileRecord(fileMap.get(generate.getFileId())));
        // 设置详情信息
        detailList.forEach(detail -> {
            // 设置item信息
            var tempItemList = itemMap.get(detail.getId());
            if (tempItemList != null) {
                tempItemList.forEach(item -> {
                    item.setCommitList(commitItemMap.getOrDefault(item.getId(), List.of()));
                    item.setGenerateList(generateMap.get(item.getId()));
                });
            }
            detail.setItemList(itemMap.get(detail.getId()));
            detail.setFileRecord(fileMap.get(detail.getFileId()));
            detail.setCommitList(commitDetailMap.getOrDefault(detail.getId(), List.of()));
        });
        // 设置状态信息
        var flag = detailList.stream().anyMatch(detail -> detail.getStatus() == 1 || detail.getStatus() == 2);
        vo.setStatus(flag ? 1 : 2);
        vo.setCommitList(commitTypeMap.getOrDefault(1, List.of()));
        vo.setDetailList(detailList);
        return vo;
    }
}
